using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using QTool.Binary;
using QTool.NetFrame;

namespace QTool.NetFrame
{
    public class InputAction:IKey<byte>
    {
        public byte Key { get; set; }
        public byte[] value;
        public System.Action<InputAction> OnStateChange;
        public FixVector2 ReadVector2()
        {
            if (value == null||value.Length==0) return FixVector2.Zero;
            return QSerialize.Deserialize<FixVector2>(value) ;
        }
        public FixVector3 ReadVector3()
        {
            if (value == null || value.Length == 0) return FixVector3.Zero;
            return QSerialize.Deserialize<FixVector3>(value);
        }
        public bool ReadBool()
        {
            if (value == null || value.Length == 0) return false;
            return QSerialize.Deserialize<Fix64>(value)>0.9f;
        }
        public override string ToString()
        {
            return Key + ":" + value?.Length;
        }
    }
    public struct InputEvent:IQSerialize,IKey<byte>
    {
        public const byte AddPlayer = byte.MaxValue;

        public const byte LoadScene = 200;
        public const byte SyncCheck = 201;
        public byte Key { get => id; set => id = value; }
        public byte id;
        public byte[] bytes;

        public void Read(QBinaryReader read)
        {
            id = read.ReadByte();
            bytes = read.ReadBytes();
      
        }

        public void Write(QBinaryWriter write)
        {
            write.Write(id);
            write.Write(bytes);
        }
        public string ReadString()
        {
            if (bytes == null || bytes.Length == 0) return "";
            return QSerialize.Deserialize<string>(bytes);
        }
        public override string ToString()
        {
            return id + ":" + bytes.Length;
        }
    }
	public class InputList : List<InputEvent>, IQSerialize, IKey<byte>
	{
		public byte Key { get; set; }
		public InputList()
		{

		}
		public InputList(int count):base(count)
		{

		}

		public void Read(QBinaryReader read)
        {
            Key = read.ReadByte();
            var byteCount =read.ReadByte();
            for (int i = 0; i < byteCount; i++)
            {
                if (byteCount >= Count)
                {
                    Add(default);
                }
                this[i] = read.ReadObject<InputEvent>();
            }
        }
        public void Write(QBinaryWriter write)
        {
            write.Write(Key);
            var byteCount = (byte)Count;
            write.Write(byteCount);
            for (int i = 0; i < byteCount; i++)
            {
                write.WriteObject(this[i]);
            }
        }
       
    }
    public class FrameData : IQSerialize, IKey<int>
    {
        public int Key { get => id; set => id = value; }
        public int id;

        public QDictionary<byte,InputList> InputLists = new QDictionary<byte, InputList>((key)=>new InputList { Key = key });
        public void SetInputList(byte playerId, List<InputEvent> targetFrame)
        {
            InputLists[playerId].AddRange(targetFrame);
        }
        public void AddPlayer(ClientInfo client)
        {
            InputLists[client.playerId].Add(new InputEvent
            {
                id = InputEvent.AddPlayer,
                bytes = QSerialize.Serialize(client)
            }) ; ;
        }
        public void Clear()
        {
            InputLists.Clear();
        }
        public void Read(QBinaryReader read)
        {
            id= read.ReadInt32();
            var count = read.ReadByte();
            InputLists.Clear();
            for (int i = 0; i < count; i++)
            {
                InputLists.Add(read.ReadObject<InputList>());
            }
        }

        public void Write(QBinaryWriter write)
        {
            write.Write(id);
            var byteCount = (byte)InputLists.Count;
            write.Write(byteCount);
			foreach (var kv in InputLists)
			{
				write.WriteObject(kv.Value);
			}
        }
    }
    public class InputActions:IKey<byte>
    {
        public InputAction this[byte index]
        {
            get
            {
                return inputActions[index];
            }

        }
        public InputAction this[string key]
        {
            get
            {
                return inputActions[QNetManager.InputIndex[key]];
            }
        }
        QDictionary<byte ,InputAction> inputActions =new QDictionary<byte, InputAction>((key)=>new InputAction {Key=key });

        public byte Key { get ; set ; }
        public static System.Action<byte,InputEvent> PlayerEvent;
        public void Trigger(InputEvent inputEvent)
        {
            if (inputEvent.id>=200)
            {
                PlayerEvent?.Invoke(Key,inputEvent);
                return;
            }
            inputActions[inputEvent.id].value = inputEvent.bytes;
            inputActions[inputEvent.id].OnStateChange?.Invoke(inputActions[inputEvent.id]);
        }
    }
}

